package cn.hg.base.jfinal.controller;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import com.jfinal.core.Controller;
import com.jfinal.core.NotAction;
import com.jfinal.json.FastJson;
import com.jfinal.json.Json;
import com.jfinal.kit.HttpKit;
import com.jfinal.kit.Kv;
import com.jfinal.upload.UploadFile;

import cn.hg.base.kit.RequestKit;

/**
 * 基础Controller，里面的很多方法是从JBoot中照搬过来的
 *
 * @author Golly
 */
public abstract class BaseController extends Controller {

	private static final String BODY_STRING_ATTR = "__body_str";
	private static final Object NULL_OBJ = new Object();
	private String rawData;

	/**
	 * 获取当前网址
	 *
	 * @return
	 */
	@NotAction
	public String getBaseUrl () {
		HttpServletRequest req = this.getRequest();
		int port = req.getServerPort();
		return port == 80 ? String.format("%s://%s%s", req.getScheme(), req.getServerName(), req.getContextPath())
			: String.format("%s://%s%s%s", req.getScheme(), req.getServerName(), ":" + port, req.getContextPath());
	}

	@NotAction
	public String getBodyString () {
		Object object = this.getAttr(BaseController.BODY_STRING_ATTR);

		if (object == BaseController.NULL_OBJ) {
			return null;
		}

		if (object != null) {
			return (String) object;
		}

		object = HttpKit.readData(this.getRequest());

		if (object == null) {
			this.setAttr(BaseController.BODY_STRING_ATTR, BaseController.NULL_OBJ);
		} else {
			this.setAttr(BaseController.BODY_STRING_ATTR, object);
		}

		return (String) object;
	}

	/**
	 * 获取ip地址
	 *
	 * @return
	 */
	@NotAction
	public String getIPAddress () { return RequestKit.getIpAddress(this.getRequest()); }

	/**
	 * 将前端传入的参数包装成KV，方便查询时使用
	 *
	 * @return
	 */
	@NotAction
	public Kv getParaMapToKv () {
		Kv kv = Kv.create();

		for (String key : this.getParaMap().keySet()) {
			// kv.set(key, this.getParaMap().get(key));
			kv.set(key, this.getPara(key));
		}

		return kv;
	}

	/**
	 * 获取 http 请求 body 中的原始数据，通常用于接收 json String 这类数据
	 * <p>
	 * 可多次调用此方法，避免掉了 HttpKit.readData(...) 方式获取该数据时多次调用 引发的异常
	 *
	 * @return http 请求 body 中的原始数据
	 */
	@Override
	@NotAction
	public String getRawData () {

		if (this.rawData == null) {
			this.rawData = com.jfinal.kit.HttpKit.readData(this.getRequest());
		}

		return this.rawData;
	}

	/**
	 * @param targetClass
	 *
	 * @return
	 */
	@NotAction
	public <T> T getRawDataTo (Class<T> targetClass) {
		Json json = Json.getJson();

		if (json instanceof com.jfinal.json.JFinalJson) {
			return FastJson.getJson().parse(this.getRawData(), targetClass);
		} else {
			return json.parse(this.getRawData(), targetClass);
		}

	}

	/**
	 * @return
	 */
	@NotAction
	public Kv getRawDataToKv () { return this.getRawDataTo(Kv.class); }

	/**
	 * 获取 referer
	 *
	 * @return
	 */
	@NotAction
	public String getReferer () { return RequestKit.getReferer(this.getRequest()); }

	/**
	 * 获取所有上传的文件
	 *
	 * @return
	 */
	@NotAction
	public HashMap<String, UploadFile> getUploadFilesMap () {

		if (!this.isMultipartRequest()) {
			return null;
		}

		List<UploadFile> fileList = this.getFiles();
		HashMap<String, UploadFile> filesMap = null;

		if (fileList != null && fileList.size() > 0) {
			filesMap = new HashMap<>();

			for (UploadFile ufile : fileList) {
				filesMap.put(ufile.getParameterName(), ufile);
			}

		}

		return filesMap;
	}

	/**
	 * 获取ua
	 *
	 * @return
	 */
	@NotAction
	public String getUserAgent () { return RequestKit.getUserAgent(this.getRequest()); }

	/**
	 * 默认的Index方法
	 */
	public abstract void index ();

	/**
	 * 是否是ajax请求
	 *
	 * @return
	 */
	@NotAction
	public boolean isAjaxRequest () { return RequestKit.isAjaxRequest(this.getRequest()); }

	/**
	 * 是否是IE浏览器
	 *
	 * @return
	 */
	@NotAction
	public boolean isIEBrowser () { return RequestKit.isIEBrowser(this.getRequest()); }

	/**
	 * 是否是手机浏览器
	 *
	 * @return
	 */
	@NotAction
	public boolean isMoblieBrowser () { return RequestKit.isMoblieBrowser(this.getRequest()); }

	/**
	 * 是否是multpart的请求（带有文件上传的请求）
	 *
	 * @return
	 */
	@NotAction
	public boolean isMultipartRequest () { return RequestKit.isMultipartRequest(this.getRequest()); }

	@NotAction
	public boolean isPostRequest () { return RequestKit.isPostRequest(this.getRequest()); }

	/**
	 * 是否是微信浏览器
	 *
	 * @return
	 */
	@NotAction
	public boolean isWechatBrowser () { return RequestKit.isWechatBrowser(this.getRequest()); }

	@NotAction
	public void renderAjaxFailed (String code, String msg) {
		this.renderAjaxFailed(code, msg, null);
	}

	@NotAction
	public void renderAjaxFailed (String code, String msg, Kv kv) {
		Map<String, Object> retMap = new HashMap<>();
		retMap.put("code", code);
		retMap.put("msg", msg);

		if (kv != null) {

			for (Object key : kv.keySet()) {
				retMap.put((String) key, kv.get(key));
			}

		}

		this.renderJson(retMap);
	}

	@NotAction
	public void renderAjaxSuccessed () {
		this.renderAjaxFailed("0", null, null);
	}

	@NotAction
	public void renderAjaxSuccessed (Kv kv) {
		this.renderAjaxFailed("0", null, kv);
	}

}
